<template>
  <div>
    <div class="wc-content fc fc-theme-standard">
      <div class="fc-header-toolbar fc-toolbar ">
        <div class="fc-toolbar-chunk">
          <h2 class="fc-toolbar-title">{{ yearMonth }}</h2>
        </div>
        <div class="fc-toolbar-chunk"></div>
        <div class="fc-toolbar-chunk">
          <button :disabled="isCurMonth()" @click="nowMonth()" class="fc-today-button fc-button fc-button-primary" type="button">今天</button>
          <div class="fc-button-group">
            <button @click="prevMonth()" class="fc-prev-button fc-button fc-button-primary" type="button" aria-label="prev"><span class="fc-icon fc-icon-chevron-left"></span></button>
            <button @click="nextMonth()" class="fc-next-button fc-button fc-button-primary" type="button" aria-label="next"><span class="fc-icon fc-icon-chevron-right"></span></button>
          </div>
        </div>
      </div>
      <div class="day-name-box">
        <div v-for="(weekName, weekIndex) in weekNameArray" :key="weekIndex" class="day-name-item">{{ weekName }}</div>
      </div>
      <div class="wc-date-box" v-if="monthArray.length">
        <div class="week-box" v-for="(empty, weekIndex) in new Array(totalWeek)" :key="weekIndex">
          <div class="wc-date-item" v-for="(empty1, dateIndex) in new Array(7)"
               :key="dateIndex"
               :disable="!isCurSelectMonth(monthArray[weekIndex * 7 + dateIndex].year, monthArray[weekIndex * 7 + dateIndex].month)"
               :class="{'wc-holiday': !needWork(monthArray[weekIndex * 7 + dateIndex]), 'wc-today': isToday(monthArray[weekIndex * 7 + dateIndex]) }">
            <span v-show="false">{{ tempDate = monthArray[weekIndex * 7 + dateIndex] }}</span>
            <div class="wc-date-name">
              <span class="date-num" :class="{}">{{ tempDate.date }}</span>
              <span class="holiday-name">{{ (_holiday = getHoliday(tempDate)) && _holiday.name || '' }}</span>
              <div class="work-type-tip" :class="{'tip-holiday': getWorkTypeByDate(tempDate) === '休'}">{{ getWorkTypeByDate(tempDate) }}</div>
            </div>
            <!--星期天的格子显示任务列表-->
            <div class="wc-task-list" v-if="new Date(tempDate.year, tempDate.month - 1, tempDate.date).getDay() === 0">
              <p v-show="false">{{ tempTask = getTaskByDate(tempDate.year, tempDate.month, tempDate.date) }}</p>
              <div class="wc-task-group" v-for="(taskGroup, gi) in tempTask" :key="gi">
                <div class="wc-task" v-for="(task, ti) in taskGroup"
                     :key="ti"
                     :style="{width: task.duration / calendarOptions.workHour * 100 + '%', left: task.left + '%'}"
                     @click="calendarOptions.taskClick(task)"
                     :class="[!task.isEnd && 'no-end' , !task.isStart && 'no-start', task.class]">
                  {{ task.title + ' ' + new Date(task.startTime).toString() }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import './work-calendar.css';
import './work-calendar-main.css'
import dayjs from 'dayjs'
import DateUtil from './date-util'
import TaskUtil from "./task-util";

let formatYMD = 'YYYY/MM/DD';
export default {
  name: 'WorkCalendar',
  props: ['options'],
  data() {
    return {
      year: undefined,
      month: undefined,
      day: undefined,
      date: undefined,
      monthName: ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'],
      weekNameArray: ['日', '一', '二', '三', '四', '五', '六'],
      monthArray: [],
      taskList: [],
      calendarOptions: {
        format: 'YYYY-MM-DD HH:mm:ss',
        // workHour: 8,
        // workStartTime: '9:00',
        // workEndTime: '18:30',
        // workBreakStartTime: '12:30',
        // workBreakEndTime: '14:00',
        date: new Date(),
        workHour: 7.5,
        workStartTime: '9:30',
        workEndTime: '18:30',
        workBreakStartTime: '12:00',
        workBreakEndTime: '13:30',
        Holiday: [],
        Workday: [],
        TaskData: [],
        taskClick(task) {
          let taskClone = JSON.parse(JSON.stringify(task))
          console.log(JSON.stringify(taskClone, null, "\t"))
        }
      },
    }
  },
  methods: {
    init() {
      let options = Object.assign(this.calendarOptions, this.options)
      // 处理任务数据以正确显示在日历视图
      this._workStartTime = DateUtil.hm2num(this.calendarOptions.workStartTime);
      this._workEndTime = DateUtil.hm2num(this.calendarOptions.workEndTime);
      this._workBreakStartTime = DateUtil.hm2num(this.calendarOptions.workBreakStartTime);
      this._workBreakEndTime = DateUtil.hm2num(this.calendarOptions.workBreakEndTime);
      this.taskList = [];

      if (options.TaskData[0] && options.TaskData[0] instanceof Array) {
        for (let j in options.TaskData) {
          let tempGroupList = [];
          let taskListStack = options.TaskData[j]
          for (let i = taskListStack.length - 1; i >= 0; i--) {
            let taskStack = taskListStack[i];
            let task = TaskUtil.taskStack2Task(taskStack)
            this.computeTask(task, tempGroupList);
          }
          this.taskList.push(tempGroupList);
        }
      } else {
        let tempGroupList = [];
        for (let i = options.TaskData.length - 1; i >= 0; i--) {
          let taskStack = options.TaskData[i];
          let task = TaskUtil.taskStack2Task(taskStack)
          this.computeTask(task, tempGroupList);
        }
        this.taskList.push(tempGroupList);
      }

      // 计算左侧偏移量
      this.taskList.forEach(taskGroupList => {
        taskGroupList.forEach(task => {
          let taskStartHm = task.startTime.getHours() + task.startTime.getMinutes() / 60;
          if (taskStartHm <= this._workBreakStartTime)
            task.left = (taskStartHm - this._workStartTime) / this.calendarOptions.workHour * 100;
          else
            task.left = (this._workBreakStartTime - this._workStartTime + (taskStartHm - this._workBreakEndTime)) / this.calendarOptions.workHour * 100
          task.left += task.startTime.getDay() * 100;
        })
      })
      this.calendarOptions = options;
      this.render(this.calendarOptions.date)
    },
    /**
     * 获取该月的总天数
     * @return {number}
     */
    totalDayByMonth(year, month) {
      return new Date(year, month, 0).getDate();
    },
    /**
     * 获取该月1号是星期几
     * @return {number} 1 2 3 4 5 6 7
     */
    firstDayByMonth(year, month) {
      return new Date(year, month - 1, 1).getDay();
    },
    /**
     * 获取x到y之间的数：如2-5 => [2, 3, 4, 5]
     * @return {number[]}
     */
    range(x, y, year, month) {
      const ary = Array();
      let i = 0; // 必须从0开始，否则.length获取的长度不准确
      for (x; x <= y; x++) {
        ary[i] = {
          year: year,
          month: month,
          date: x
        };
        i++;
      }
      return ary;
    },
    /**
     * 当前选择的月份是否是现在的月份
     */
    isCurMonth() {
      let format = 'YYYY/MM/01';
      let date = new Date(this.year, this.month - 1, 1)
      return dayjs(date).format(format) === dayjs().format(format);
    },
    /**
     * 传参的月份是否是当前选择的月份
     * @param year
     * @param month
     * @return {boolean}
     */
    isCurSelectMonth(year, month) {
      let format = 'YYYY/MM/01';
      let date = new Date(year, month - 1, 1)
      let cutSelect = new Date(this.year, this.month - 1, 1)
      return dayjs(date).format(format) === dayjs(cutSelect).format(format);
    },
    /**
     * 是否是今天
     */
    isToday(dateInfo) {
      let temp = new Date(dateInfo.year, dateInfo.month - 1, dateInfo.date)
      let tempYMD = dayjs(temp).format(formatYMD)
      let nowYMD = dayjs().format(formatYMD)
      return tempYMD === nowYMD;
    },
    /**
     * 是否是节假日：周六周日 法定节假日
     * @param date
     */
    needWork(dateInfo) {
      let workType = this.getWorkTypeByDate(dateInfo);
      if (workType === '休')
        return false
      if (workType === '班')
        return true
      // 周六周日
      let date = this.dateInfo2Date(dateInfo);
      return !(date.getDay() === 6 || date.getDay() === 0);

    },
    /**
     * 获取节假日信息
     */
    getHoliday(dateInfo) {
      let date = this.dateInfo2Date(dateInfo);
      return this.findDateInArray(this.calendarOptions.Holiday, date);
    },
    /**
     * 将dateInfo转为日期格式
     * @param dateInfo
     */
    dateInfo2Date(dateInfo) {
      try {
        if (typeof dateInfo === 'string')
          return new Date(dateInfo)
        let time = dateInfo.getTime()
        return new Date(time)
        // eslint-disable-next-line no-empty
      } catch (e) {
      }
      let temp = new Date(dateInfo.year, dateInfo.month - 1, dateInfo.date)
      return temp;
    },
    /**
     * 获取该日的工作类型：班/休/正常
     */
    getWorkTypeByDate(dateInfo) {
      let date = this.dateInfo2Date(dateInfo);
      let workday = this.findDateInArray(this.calendarOptions.Workday, date);
      if (workday)
        return '班';
      let holiday = this.getHoliday(dateInfo);
      if (holiday)
        return '休';
      return '';
    },
    /**
     * 在Array中寻找日期相同的函数的调用方法
     * @param item
     * @private
     */
    findDateInArray(dateArray, date) {
      return dateArray.find(item => {
        return dayjs(date).format(formatYMD) === dayjs(new Date(item.date)).format(formatYMD)
      })
    },
    /**
     * 渲染日历
     */
    render(date) {
      const _Date = date || new Date(), _curYear = _Date.getFullYear(), _curMonth = _Date.getMonth() + 1, _curDay = _Date.getDate();
      let firstDayByMonth = this.firstDayByMonth(_curYear, _curMonth);
      let totalDayByMonth = this.totalDayByMonth(_curYear, _curMonth);
      // 当月的总天数的数组
      let monthArray = this.range(1, totalDayByMonth, _curYear, _curMonth)

      // 第一排的空位数 用 上月后几位日期 填补
      if (firstDayByMonth % 7 != 0) {
        let prevDay = this.totalDayByMonth(_curYear, (_curMonth - 1)); // 上月的总天数
        let aryFirst = this.range(prevDay - firstDayByMonth + 1, prevDay, _curYear, _curMonth - 1);
        monthArray = aryFirst.concat(monthArray);
      }

      // 最后排的空位数 用 下月的前几位日期填补
      let lenLast = monthArray.length, last = 7 - lenLast % 7;
      if (last % 7 !== 0) {
        let nextMonthArray = this.range(1, last, _curYear, _curMonth + 1);
        monthArray = monthArray.concat(nextMonthArray);
      }
      this.monthArray = monthArray
      this.year = _curYear
      this.month = _curMonth
      this.day = _curDay
      this.date = new Date(_curYear, _curMonth - 1, _curDay)
    },
    nextMonth() {
      this.date.setMonth(this.date.getMonth() + 1);
      this.render(this.date)
    },
    prevMonth() {
      this.date.setMonth(this.date.getMonth() - 1);
      this.render(this.date)
    },
    nowMonth() {
      this.render(new Date())
    },
    /**
     * 获取该周的任务
     */
    getTaskByDate(y, m, d) {
      let date = new Date(y, m - 1, d);
      let res = Array.from(this.taskList, taskGroup => {
        let groupRes = taskGroup.filter(item => {
          if (!item.startTime) return false
          return DateUtil.isSameWeek(item.startTime, date)
        })
        return groupRes;
      })
      return res;
    },
    /**
     * 获取需要工作的时间
     * @param hm 如：9.5 （9点半）
     */
    _getNeedWorkHour(hm) {
      if (hm <= this._workBreakStartTime)
        return this._workBreakStartTime - hm + (this._workEndTime - this._workBreakEndTime);
      else
        return this._workEndTime - hm;
    },
    /**
     * 下一天是否是节假日
     */
    _isNextDateHoliday(date) {
      let temp = date.setDate(date.getDate() + 1)
      return !this.needWork(temp)
    },
    _isTodayHoliday(date) {
      return !this.needWork(date)
    },
    /**
     * 计算任务是否跨过休息时间，如果跨过休息时间 分割为两个任务
     * @param task
     */
    computeTask(task, tempGroupList) {
      if (this._isTodayHoliday(task.endTime)) {
        if (task.duration > 0) {
          tempGroupList.push({
            title: task.title,
            startTime: task.startTime,
            duration: task.duration,
            endTime: task.endTime,
            remainingHour: task.remainingHour,
            isStart: task.isStart,
            isEnd: task.isEnd,
            class: task.class,
            data: task.data
          })
        }
        let dateInfo = DateUtil.getDateInfo(task.endTime)
        task.startTime = new Date(`${dateInfo.Y}/${dateInfo.M + 1}/${dateInfo.D} ${this.calendarOptions.workStartTime}:00`)
        task.startTime = DateUtil.addDate(task.endTime, 1)
        task.duration = 0;
        task.endTime = new Date(task.startTime)
        task.isStart = false
        this.computeTask(task, tempGroupList)
      } else {
        let endHm = DateUtil.getHmByDate(task.endTime);
        let needWorkHour = this._getNeedWorkHour(endHm);
        if (task.remainingHour > needWorkHour) {
          task.remainingHour -= needWorkHour;
          task.duration += needWorkHour;
          let dateInfo = DateUtil.getDateInfo(task.endTime)
          task.endTime = new Date(`${dateInfo.Y}/${dateInfo.M + 1}/${dateInfo.D} ${this.calendarOptions.workStartTime}:00`)
          task.endTime = DateUtil.addDate(task.endTime, 1)
          this.computeTask(task, tempGroupList)
        } else {
          let theDateWorkHour = task.remainingHour;
          task.duration += theDateWorkHour
          task.remainingHour = 0;
          let endHm = DateUtil.getHmByDate(task.endTime)
          let newEndHm = theDateWorkHour + endHm;
          if (endHm < this._workBreakStartTime && newEndHm > this._workBreakStartTime)
            newEndHm += this._workBreakEndTime - this._workBreakStartTime;
          task.endTime.setHours(parseInt(newEndHm))
          task.endTime.setMinutes(newEndHm % 1 * 60)
          tempGroupList.push({
            title: task.title,
            startTime: task.startTime,
            duration: task.duration,
            endTime: task.endTime,
            remainingHour: task.remainingHour,
            isStart: task.isStart,
            isEnd: true,
            class: task.class,
            data: task.data
          })
        }
      }
    }
  },
  created: function () {
    this.init()
  },
  mounted() {
//     window.$calendarView = this;
//     let $fullCalendar = window.$fullCalendar = this.$refs.fullCalendar.getApi();
//     this.$get('/task/list/bychuliid', { status: '已完成', chuliId: 4 }, res => {
//       res && res.forEach(item => {
//         let e = {
//           title: item.title + new Date(item.jieZhi).Format('MM-dd hh:mm'),
//           start: item.yujikaishi,
//           end: item.jieZhi
//         }
//         console.log(e)
//         $fullCalendar.addEvent(e)
//       })
//     })
  },
  computed: {
    totalWeek() {
      return this.monthArray.length / 7;
    },
    yearMonth() {
      return dayjs(new Date(this.year, this.month - 1, 1)).format('YYYY年MM月')
    }
  }
}
</script>

